/*
 * @Description  : 工具类
 * @Autor        : 杜康
 * @Date         : 2023-03-07 16:38:49 +0800
 * @LastEditors  : 杜康
 * @LastEditTime : 2023-08-03 15:46:45 +0800
 */
import * as echarts from "echarts";
import { Message } from "element-ui";
import Cookies from "js-cookie";
import { isEmpty, isObject } from "lodash";

/**
 * @description: 判断HTML元素是否存在
 * @param {*} elId
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-26 15:52:35 +0800
 */
export const hasEle = (elId) => {
  return Boolean(document.getElementById(elId));
};

/**
 * @description: 销毁已有ECharts实例
 * @param {*} domId
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-26 15:58:43 +0800
 */
export const disposeEcharts = (domId) => {
  echarts.dispose(document.getElementById(domId));
};
/* eslint-disable */
/**
 * @description: 生成梯形图配置
 * @param {*} data
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-24 17:46:52 +0800
 */
export const getLadderOption = (data) => {
  const { series } = data;
  const funnelData = [];
  const values = [];
  const styleNums = [683513, 183680];
  const paddings = [
    [0, 0, 0, 0],
    [0, 0, 30, 0],
  ];
  /* eslint-disable */
  series?.forEach((item, index) => {
    if (index < 2) {
      const { name, value } = item;
      values.includes(value) ? "" : values.push(value);
      funnelData?.push({
        value: styleNums[index],
        name: `${Number(value)} ${name}`,
        label: {
          fontSize: 16,
          color: "#000",
          padding: paddings[index],
          rich: {},
        },
      });
    }
  });
  const max = Math.max(...styleNums);
  const option = {
    color: ["#36DC88", "#F9A646"],
    backgroundColor: "",
    animation: false,
    series: [
      {
        type: "funnel",
        left: "5%",
        right: "5%",
        bottom: "5%",
        width: "90%",
        gap: 2,
        max,
        label: {
          show: true,
          position: "inside",
        },
        data: funnelData,
      },
    ],
  };
  return option;
};

/**
 * @description: 生成漏斗图配置
 * @param {*} data
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-24 17:48:33 +0800
 */
export const getFunnelOption = (data) => {
  const { series } = data;
  const funnelData = [];
  const values = [];
  const colors = [];
  series?.forEach((item) => {
    const { name, color, value } = item;
    values?.includes(value) ? "" : isEmpty(value) ? "" : values?.push(value);
    colors?.includes(color) ? "" : isEmpty(color) ? "" : colors?.push(color);
    funnelData?.push({
      value: Number(value),
      name: `${Number(value)} ${name}`,
      label: {
        fontSize: 16,
        color: "#000",
        padding: [0, 0, 30, 0],
        rich: {},
      },
    });
  });
  const max = Math.max(...values);
  const option = {
    color: isEmpty(colors) ? ["#36DC88", "#F9A646"] : colors,
    backgroundColor: "",
    animation: false,
    series: [
      {
        type: "funnel",
        left: "5%",
        right: "5%",
        bottom: "5%",
        width: "90%",
        gap: 2,
        max,
        label: {
          show: true,
          position: "inside",
        },
        data: funnelData,
      },
    ],
  };
  return option;
};

// 生成图片Map
export const optMap = {
  LadderChart: getLadderOption,
  FunnelChart: getFunnelOption,
};
// 需要生成Base64图片的组件集合
export const imgCommponents = ["LadderChart", "FunnelChart"];

/**
 * @description: 获取ECharts 图表 Base64图片数据
 * @param {*} data
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-24 15:44:58 +0800
 */
export const getChartBase64 = (data, type = "") => {
  const { id, result, showType } = data;
  type = isEmpty(type) ? showType : type;
  const elId = `myDiv${id}`;
  if (hasEle(elId)) {
    disposeEcharts(elId);
  } else {
    const myDiv = document.createElement("div");
    myDiv.id = elId;
    myDiv.style = `width: 800px; height: 400px; position: absolute; top: -9999px;`;
    document.body.appendChild(myDiv);
  }
  const myChart = echarts.init(document.getElementById(elId));
  const option = optMap?.[type](result);
  myChart?.setOption(option);
  const picture = myChart?.getDataURL();
  return { ...data, picture, result: "", style: ".png" };
};

/**
 * message提示框
 * @param {String} text 提示文字 1 success 2 error 3 warning
 * @param {Boolean} type 提示类型
 * @param {Number} duration 显示时间
 * @param {Boolean} showClose 是否显示关闭按钮
 */
export const showMsg = (text, type = 1, duration = 5) => {
  if (type === 1) {
    Message.success(text, duration);
  } else if (type === 2) {
    Message.error(text, duration);
  } else {
    Message.warning(text, duration);
  }
};

/**
 * @description: 报告API接口报错提示
 * @param {*} code
 * @param {*} msg
 * @param {*} type
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-19 18:43:02 +0800
 */
export const handlerReportMsg = (code, msg, type = 2) => {
  if (type === 2) {
    const MSG = isEmpty(code)
      ? msg
      : `API Error Code: ${code}, API Error Massage: ${msg}`;
    showMsg(MSG, 2);
  } else {
    showMsg(msg, type);
  }
};

/**
 * @description: 自定义判断元素类型
 * @param {*} obj
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-16 12:04:34 +0800
 */
export const toType = (obj) => {
  return Object.toString
    .call(obj)
    .match(/\s([a-zA-Z]+)/)[1]
    .toLowerCase();
};

/**
 * @description: 滤参
 * @param {*} o
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-16 12:04:08 +0800
 */
export const filterNull = (o) => {
  const params = {};
  for (var key in o) {
    if (o[key] !== null && o[key] !== undefined) {
      if (this.toType(o[key]) === "string") {
        params[key] = o[key].trim();
      } else {
        params[key] = o[key];
      }
    }
  }
  return params;
};

/**
 * @description: 本地存储
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-16 12:03:35 +0800
 */
export const storage = {
  session: {
    get(key) {
      return sessionStorage[key];
    },
    set(key, val, isCover) {
      if (sessionStorage[key] && !isCover) {
        alert("[" + key + "]已经存在");
      } else {
        if (sessionStorage[key]) {
          alert("[" + key + "]被覆盖");
        }
        sessionStorage[key] = val;
      }
    },
  },
  local: {
    get(key) {
      return localStorage[key];
    },
    set(key, val, isCover) {
      if (localStorage[key] && !isCover) {
        alert("[" + key + "]已经存在");
      } else {
        if (localStorage[key]) {
          alert("[" + key + "]被覆盖");
        }
        localStorage[key] = val;
      }
    },
  },
};

/**
 * @description -- 从url中解析参数
 * @param {String} url
 */
export const getParams = (url) => {
  const keyValueArr = url.split("?")[1].split("&");
  const paramObj = {};
  keyValueArr.forEach((item) => {
    const keyValue = item.split("=");
    paramObj[keyValue[0]] = keyValue[1];
  });
  return paramObj;
};

/**
 * @Description: 设置Storage 对应key的值
 * @param {*} key
 * @param {*} value
 * @return {*}
 * @author: 李永兵
 * @Date: 2022-10-15 12:14:45 +0800
 */
export const setStorageItem = (key, value) => {
  window.localStorage.setItem(key, value);
};

/**
 * @description: 获取Storage 对应key的值
 * @param {*} key
 * @return {*}
 * @author: 李永兵
 * @Date: 2022-10-15 12:15:27 +0800
 */
export const getStorageItem = (key) => {
  return window.localStorage.getItem(key);
};

/**
 * @description: 移除Storage 对应key的值
 * @param {*} key
 * @return {*}
 * @author: 李永兵
 * @Date: 2022-10-15 12:15:58 +0800
 */
export const removeStorageItem = (key) => {
  window.localStorage.removeItem(key);
};

/**
 * @description: 清空Cookie
 * @return {*}
 * @author: 李永兵
 * @Date: 2022-10-15 12:16:59 +0800
 */
export const clearStorage = () => {
  window.localStorage.clear();
};

/**
 * @description: 首字母大写
 * @param {*} text
 * @return {*}
 * @author: 杜康
 * @Date: 2023-02-20 16:36:57 +0800
 */
export const firstLetterCap = (text) => {
  return text?.charAt(0)?.toUpperCase() + text?.slice(1);
};

/**
 * @description: 判断字符串是否为JSON对象
 * @param {*} str
 * @return {*}
 * @author: 李永兵
 * @Date: 2023-02-21 15:59:35 +0800
 */
export const isJSON = (str) => {
  if (typeof str == "string") {
    try {
      var obj = JSON.parse(str);
      if (typeof obj == "object" && obj) {
        return true;
      } else {
        return false;
      }
    } catch (e) {
      return false;
    }
  }
};

/**
 * @description: 设置Cookie
 * @param {*} name Key
 * @param {*} value 值
 * @return {*}
 * @author: 李永兵
 * @Date: 2023-02-21 15:49:35 +0800
 */
export const setCookie = (name, value = null) => {
  Cookies.set(name, value);
};

/**
 * @description: 读取Cookie
 * @param {*} name Key
 * @return {*}
 * @author: 李永兵
 * @Date: 2023-02-21 15:25:59 +0800
 */
export const getCookie = (name) => {
  const VALUE = Cookies.get(name);
  return isJSON(VALUE) ? JSON?.parse(VALUE) : VALUE;
};

/**
 * @description: 清空Cookie
 * @return {*}
 * @author: 李永兵
 * @Date: 2023-02-21 15:12:25 +0800
 */
export const clearAllCookie = () => {
  // eslint-disable-next-line no-useless-escape
  const KEYS = document.cookie.match(/[^ =;]+(?=\=)/g);
  KEYS?.forEach((item) => {
    if (!isEmpty(item)) {
      setCookie(item);
    }
  });
};

export const headerCellStyle = {
  background: "rgba(19,130,255,0.06)",
  color: "#606266",
  padding: "12px 0px",
  fontSize: "14px",
};

/**
 * @description: 处理动态合并表格数据、获取合并表格相关数据
 *               最后一列是计算是否需要合并
 * @param {*} data
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-16 12:23:48 +0800
 */
export const mergeTable = (data) => {
  // headers 动态表头
  // mergeColumns 需要合并的列
  // body 渲染数据 表格数据
  const { headers, mergeColumns, body } = data;
  const bodyLen = body?.length;
  // 存放所有的表头 一定要与tableData一致
  const colFields = [];
  headers?.forEach((item) => {
    const { key } = item;
    if (!colFields?.includes(key)) {
      colFields?.push(key);
    }
  });
  const colLen = colFields?.length;
  // 存储合并单元格的开始位置
  const mergeCells = [];
  // data就是我们从后台拿到的数据
  body?.forEach((item, index) => {
    const row = index;
    if (row === 0) {
      colFields?.forEach((col, key) => {
        mergeCells[index * colLen + key] = {
          rowspan: 1,
          colspan: 1,
        };
      });
    } else {
      let rowNextIndex = 0;
      colFields?.forEach((col, key) => {
        if (mergeColumns?.includes(col)) {
          const cellIndex = row * colLen + key;
          const rowIndex = (row - 1) * colLen + key;
          // 指定合并哪些列
          if (body[index][mergeColumns[0]] !== body[row - 1][mergeColumns[0]]) {
            // 哪些不合并:第一列不一样的,不合并
            mergeCells[cellIndex] = {
              rowspan: 1,
              colspan: 1,
            };
            // 处理最后一行 此处受限于 【需要合并的列】数据
            if (index === bodyLen - 1) {
              if (
                body[index][colFields[key]] === body[index][colFields[key + 1]]
              ) {
                // 第一个单元格数据  等于  第二个单元格数据是逻辑
                const rowItem = mergeCells[rowIndex];
                rowNextIndex = rowIndex + 1;
                mergeCells[cellIndex] = {
                  rowspan: 1,
                  colspan: 1 + rowItem.colspan,
                };
              } else if (rowNextIndex === rowIndex) {
                // 解决合并单元格之后下一个单元格设置
                mergeCells[cellIndex] = {};
              } else {
                // 其他默认不合并
                mergeCells[cellIndex] = {
                  rowspan: 1,
                  colspan: 1,
                };
              }
            }
          } else if (
            body[index][colFields[key]] === body[row - 1][colFields[key]]
          ) {
            const beforeItem = mergeCells[rowIndex];
            mergeCells[cellIndex] = {
              rowspan: 1 + beforeItem.rowspan, // 合并几列
              colspan: 1, // 合并几行
            };
            beforeItem.rowspan = 0;
            beforeItem.colspan = 0;
          } else {
            // rowspan 和 colspan 都为1表格此单元格不合并
            mergeCells[cellIndex] = {
              rowspan: 1,
              colspan: 1,
            };
          }
        }
      });
    }
  });
  // 对数据进行倒序
  const stack = [];
  colFields?.forEach((item, index) => {
    body?.forEach((row, key) => {
      const cellIndex = key * colLen + index;
      if (key === 0) {
        if (mergeCells[cellIndex]?.rowspan === 0) {
          stack?.push(mergeCells[cellIndex]);
        }
      } else {
        if (mergeCells[cellIndex]?.rowspan === 0) {
          stack?.push(mergeCells[cellIndex]);
        } else {
          stack?.push(mergeCells[cellIndex]);
          while (stack.length > 0) {
            const pop = stack?.pop();
            const len = stack?.length;
            mergeCells[(key - len) * colLen + index] = pop;
          }
        }
      }
    });
  });
  return {
    mergeCells,
    colFields,
  };
};

/**
 * @description: 多分类折线图颜色值
 * @return {*}
 * @author: 李永兵
 * @Date: 2023-02-07 16:19:00 +0800
 */
export const multiChartColors = [
  ["#CB272D", "#F53F3F", "#F98981"],
  ["#009A29", "#00B42A", "#4CD263"],
  ["#CC5120", "#F77234", "#FAAC7B"],
  ["#206CCF", "#3491FA", "#7BC0FC"],
  ["#E56000", "#FF7D00", "#FFB65D"],
  ["#0DA5AA", "#14C9C9", "#5EDFD6"],
  ["#CC9213", "#F7AD1E", "#FADC6D"],
  ["#7EB712", "#9FDB1D", "#C9E968"],
  ["#CFAF0F", "#FADC19", "#FCF26B"],
  ["#551DB0", "#722ED1", "#A871E3"],
  ["#0E42D2", "#165DFF", "#6AA1FF"],
  ["#B010B6", "#D91AD9", "#E865DF"],
  // 颜色顺序
  // ["#CB272D", "#F53F3F", "#F98981"],
  // ["#CC5120", "#F77234", "#FAAC7B"],
  // ["#E56000", "#FF7D00", "#FFB65D"],
  // ["#CC9213", "#F7AD1E", "#FADC6D"],
  // ["#CFAF0F", "#FADC19", "#FCF26B"],
  // ["#7EB712", "#9FDB1D", "#C9E968"],
  // ["#009A29", "#00B42A", "#4CD263"],
  // ["#0DA5AA", "#14C9C9", "#5EDFD6"],
  // ["#206CCF", "#3491FA", "#7BC0FC"],
  // ["#0E42D2", "#165DFF", "#6AA1FF"],
  // ["#551DB0", "#722ED1", "#A871E3"],
  // ["#B010B6", "#D91AD9", "#E865DF"],
  // "#F99057",
  // "#F9CC45",
  // "#FBE842",
  // "#B5E241",
  // "#23C343",
  // "#33D1C9",
  // "#57A9FB",
  // "#F754A8",
  // "#E13EDB",
  // "#8D4EDA",
];

/**
 * @description: 获取颜色
 * @param {*} index
 * @return {*}
 * @author: 杜康
 * @Date: 2023-04-03 17:25:01 +0800
 */
export const getChartColor = (index) => {
  const len = multiChartColors?.length;
  return index < len
    ? multiChartColors?.[index]
    : multiChartColors?.[index % len];
};

/**
 * @description: 下载文件
 * @param {*} data 数据流
 * @param {*} fileName 文件名称
 * @param {*} suffix 文件后缀
 * @return {*}
 * @author: 杜康
 * @Date: 2023-05-09 11:03:01 +0800
 */
export const publicDownLoadFile = (data, fileName, suffix) => {
  if (verifyArrayBuffer(data) || suffix === "json") {
    // 获取当前日期及时间
    const DATE = new Date().toLocaleString().replaceAll("/", "-");
    const _fileName_ = `${fileName}${DATE}`;
    const fileAllName = isEmpty(suffix)
      ? _fileName_
      : `${_fileName_}.${suffix}`;
    //  如果支持微软的文件下载方式(ie10+浏览器)
    if (window.navigator.msSaveBlob) {
      try {
        const blobObject = new Blob([data]);
        window.navigator.msSaveBlob(blobObject, fileAllName);
      } catch (e) {
        console.log(e);
      }
    } else {
      //  其他浏览器
      const url = window.URL.createObjectURL(
        new Blob([data], {
          type: "application/json,application/zip,text/csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/octet-stream",
        })
      );
      const link = document.createElement("a");
      link.style.display = "none";
      link.href = url;
      link.setAttribute("download", fileAllName);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(link.href);
    }
  }
};

/**
 * @description: 校验ArrayBuffer
 * @param {*} data
 * @return {*}
 * @author: 杜康
 * @Date: 2023-03-24 16:45:12 +0800
 */
const verifyArrayBuffer = (data) => {
  // 使用TextDecoder
  const enc = new TextDecoder(); // ，默认转utf-8
  const response = enc?.decode(new Uint8Array(data));
  if (response?.includes("code")) {
    // 文件错误时会返回code码告知错误原因，若成功直接返回文件流
    const { code, data, msg } = JSON.parse(response);
    handlerReportMsg(code, msg);
    return false;
  } else {
    return true;
  }
};

/**
 * @description: 读取相应Header中文件名
 * @param {*} headers
 * @return {*}
 * @author: 杜康
 * @Date: 2023-03-13 18:21:55 +0800
 */
export const getFileType = (headers) => {
  const contentDisposition = headers?.[`content-disposition`];
  const cds = contentDisposition?.split(";");
  const allFileName = cds
    ?.filter((item) => item.includes(`filename`))?.[0]
    ?.split("=")?.[1]
    ?.replaceAll(`"`, "");
  const firstIndex = allFileName.indexOf(".");
  const fileName =
    firstIndex > 0 ? allFileName?.substring(0, firstIndex) : allFileName;
  const fileType = firstIndex > 0 ? allFileName?.substring(firstIndex + 1) : "";
  return {
    fileName: decodeURIComponent(fileName),
    fileType,
  };
};

/**
 * @description: 聚合下载
 * @param {*} data
 * @return {*}
 * @author: 杜康
 * @Date: 2023-03-13 18:40:22 +0800
 */
export const aggregationDownloadFile = (data) => {
  const { headers, data: fileData } = data;
  const { fileName, fileType } = getFileType(headers);
  publicDownLoadFile(fileData, fileName, fileType);
};
